module Grafo where

data Grafo a = G [a] (a -> [a]) 
instance (Show a) => Show (Grafo a) where
	show (G n e) = "[\n" ++ concat (map (\x -> " " ++ show x ++ " -> " ++ show (e x) ++ "\n") n) ++ "]"


-----------------
-- EJERCICIO 1 -- 
-----------------
vacio :: Grafo a
vacio = G [] (\x -> [])


-----------------
-- EJERCICIO 2 -- 
-----------------
nodos :: Grafo a -> [a]
nodos (G ns f) = ns


-----------------
-- EJERCICIO 3 -- 
-----------------
vecinos :: Eq a => Grafo a -> a -> [a]
vecinos (G ns f) n = f n

-----------------
-- EJERCICIO 4 -- 
-----------------
			
agNodo :: Eq a => Grafo a -> a -> Grafo a
agNodo (G ns f) n | elem n ns = G ns f
		              | otherwise = G (n:ns) (\x -> if (x == n) then [] else f x)

-----------------
-- EJERCICIO 5 -- 
-----------------			
agSinRep :: Eq a => a -> [a] -> [a]
agSinRep a as | elem a as = as
              | otherwise = a:as

agEje :: Eq a => Grafo a -> (a, a) -> Grafo a
agEje (G ns f) (x, y) = G ns g
  where g t = if (t == x) then (agSinRep y (f x)) else f x


-----------------
-- EJERCICIO 6 -- 
-----------------			
k :: Eq a => [a] -> Grafo a
k ns = G ns (\x -> [n | n <- ns, n /= x])

-----------------
-- EJERCICIO 7 -- 
-----------------			
lineal :: Eq a => [a] -> Grafo a
lineal ns = G ns (\n -> next (tail (dropWhile (\y -> y /= n) ns)))

next :: [a] -> [a]
next [] = []
next (x:xs) = [x]

-----------------
-- EJERCICIO 8 -- 
-----------------			
union :: Eq a => Grafo a -> Grafo a -> Grafo a
union p q = G (unir (nodos p) (nodos q)) (\n -> unir (vecinos p n) (vecinos q n))

unir :: Eq a => [a] -> [a] -> [a]
unir xs ys = xs++[n | n <- ys, not (elem n xs)]


